/******************************************************************************\
    StdFileEx.hpp contains a class of std file object.
    Copyright (C) 2008  Victor Vinogradov (fly3333@gmail.com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
\******************************************************************************/

#ifndef __STD_FILE_HPP
#define __STD_FILE_HPP

#include <stdio.h>
#include <stdarg.h>
#include ".\Object.hpp"

class cSubStdFile : public cSubObject
{
	FILE *File;
public:
	cSubStdFile( FILE *file )
		: File( file )
	{
	}
	~cSubStdFile()
	{
		fclose( File );
	}
	FILE *Handle() const
	{
		return File;
	}
};

class cStdFile : public cObject< cSubStdFile >
{
public:
	operator FILE *()	const
	{
		if( GetSubObject() == NULL )
			return NULL;
		return GetSubObject()->Handle();
	}
	bool Open( const char *filename, const char *mode )
	{
		FILE *file = fopen( filename, mode );
		if( file == NULL )
			return false;
		cSubStdFile *sub_std_file;
		try
		{
			sub_std_file = new cSubStdFile( file );
		}
		catch( ... )
		{
			return false;
		}
		SwitchToSubObject( sub_std_file );
		return true;
	}
	int Printf( const char *format, ... )
	{
		if( GetSubObject() == NULL )
			return EOF;
		va_list arg_list;
		va_start( arg_list, format );
		int result = vfprintf( GetSubObject()->Handle(), format, arg_list );
		va_end( arg_list );
		return result;
	}
	int PrintfV( const char *format, va_list arg_list )
	{
		if( GetSubObject() == NULL )
			return EOF;
		return vfprintf( GetSubObject()->Handle(), format, arg_list );
	}
	size_t Write( const void *buffer, size_t size, size_t count )
	{
		if( GetSubObject() == NULL )
			return 0;
		return fwrite( buffer, size, count, GetSubObject()->Handle() );
	}
	size_t Read( void *buffer, size_t size, size_t count )
	{
		if( GetSubObject() == NULL )
			return 0;
		return fread( buffer, size, count, GetSubObject()->Handle() );
	}
	int Seek( long offset, int origin )
	{
		if( GetSubObject() == NULL )
			return -1;
		return fseek( GetSubObject()->Handle(), offset, origin );
	}
	long int Tell()
	{
		if( GetSubObject() == NULL )
			return -1L;
		return ftell( GetSubObject()->Handle() );
	}
	int Flush()
	{
		if( GetSubObject() == NULL )
			return EOF;
		return fflush( GetSubObject()->Handle() );
	}
	int GetChar()
	{
		if( GetSubObject() == NULL )
			return EOF;
		return fgetc( GetSubObject()->Handle() );
	}
	void UngetChar( int c )
	{
		if( GetSubObject() == NULL )
			return;
		ungetc( c, GetSubObject()->Handle() );
	}
	int PutChar( int c )
	{
		if( GetSubObject() == NULL )
			return EOF;
		return fputc( c, GetSubObject()->Handle() );
	}
	int PeekChar()
	{
		if( GetSubObject() == NULL )
			return EOF;
		int c = GetChar();
		UngetChar( c );
		return c;
	}
	void Close()
	{
		SwitchToSubObject( NULL );
	}
};

#endif
